package com.openatc.agent.service.impl;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.openatc.agent.controller.TemplateController;
import com.openatc.agent.service.AbstractControlRequest;
import com.openatc.agent.service.AscsDao;
import com.openatc.comm.data.MessageData;
import com.openatc.core.common.IErrorEnumImplInner;
import com.openatc.core.common.IErrorEnumImplOuter;
import com.openatc.core.model.InnerError;
import com.openatc.core.model.RESTRet;
import com.openatc.core.util.GsonUtil;
import com.openatc.core.util.RESTRetUtils;
import com.openatc.model.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author ：panleilei
 * @description
 * @modified By：
 * @version:
 * @date ：Created in 2024/2/28 13:43
 */
@Service(value = "control/pattern-101")
public class DirectionLock extends AbstractControlRequest {
    private Gson gson = GsonUtil.getInstance();
    @Autowired
    private AscsDao mDao;
    @Autowired
    private TemplateController templateController;
    @Override
    public RESTRet preProcess(MessageData requestData) {
        String agentId = requestData.getAgentid();
        // 第三方平台直接转发
        boolean thirdParty = isThirdParty(agentId);
        if (thirdParty) {
            return super.preProcess(requestData);
        }
        JsonElement data = requestData.getData();
        JsonElement controlData = data.getAsJsonObject().get("data");
        LockDirection directionLockData = gson.fromJson(controlData, LockDirection.class);
        // 方向锁定转换为通道锁定
        // 获取通道参数
        List<Channel> channels = getChannels(agentId);
        if (CollectionUtils.isEmpty(channels)) {
            logger.warning("get channelList failed!");
            InnerError innerError = RESTRetUtils.innerErrorObj(agentId, IErrorEnumImplInner.E_109, "get channelList failed!");
            return RESTRetUtils.errorDetialObj(IErrorEnumImplOuter.E_4001, innerError);
        }
        // 解析出需要锁定的通道号
        Set<Integer> channelIds = getLockChannelIds(directionLockData, channels);
        // 转换为通道锁定
        ControlPattern controlPattern = getControlPattern(directionLockData, channelIds);

        requestData.setData(gson.toJsonTree(controlPattern));
        return super.preProcess(requestData);
    }

    private ControlPattern getControlPattern(LockDirection directionLockData, Set<Integer> channelIds) {
        // 生成方向锁定通道信息
        List<ChannelLock> channelLocks = new ArrayList<>();
        // 要锁定的通道置为绿灯
        for (Integer channelId : channelIds) {
            channelLocks.add(new ChannelLock(channelId, 3));
        }

        // 设置方向锁定消息
        ControlPattern controlPattern = new ControlPattern();
        LockDirectionForControlPattern lockDirectionForControlPattern = new LockDirectionForControlPattern(directionLockData);
        controlPattern.setControl(16);  // 16 - 方向锁定控制
        lockDirectionForControlPattern.setChannellocKinfo(channelLocks);
        controlPattern.setData(lockDirectionForControlPattern);
        return controlPattern;
    }

    private Set<Integer> getLockChannelIds(LockDirection directionLockData, List<Channel> channels) {
        Set<Integer> channelIds = new HashSet<>();
        // 要锁定的机动车方向
        List<Integer> directions = directionLockData.getDirection();
        // 要锁定的行人方向
        List<Integer> pedDirections = directionLockData.getPeddirection();
        // 处理行人方向/机动车方向
        for (Channel channel : channels) {
            Integer type = channel.getType();
            if (type == null) continue;
            // 机动车
            if (type != 2) {
                // 通道中包含要锁定的方向
                if (CollectionUtils.containsAny(directions, channel.getRealdir())) {
                    channelIds.add(channel.getId());
                }
            }
            // 行人
            else {
                // 通道中包含要锁定的方向
                if (CollectionUtils.containsAny(pedDirections, channel.getRealdir())) {
                    channelIds.add(channel.getId());
                }
            }
        }
        return channelIds;
    }

    private boolean isThirdParty(String agentId) {
        AscsBaseModel ascsBaseModel = mDao.getAscsByID(agentId);
        return !"ocp".equals(ascsBaseModel.getProtocol());
    }


    /**
     * 获取通道参数
     * @param agentId
     * @return
     */
    private List<Channel> getChannels(String agentId) {
        // 获取通道参数
        RESTRet<JsonObject> restRet;
        try {
            restRet = (RESTRet<JsonObject>)templateController.getTemplate(agentId);
        } catch (Exception e) {
            logger.warning(agentId + " request feature Exception: " + e.getMessage());
            return null;
        }
        List<Channel> channels;
        if (restRet.isSuccess()) {
            try {
                JsonObject feature = restRet.getData();
                JsonObject param = feature.get("param").getAsJsonObject();
                 channels = gson.fromJson(param.get("channelList"), new TypeToken<List<Channel>>(){}.getType());
                System.out.println();
            } catch (Exception e){
                e.printStackTrace();
                logger.warning(agentId + " get channelList failed " + e.getMessage());
                return null;
            }
        } else {
            logger.warning("Request feature error: " + restRet);
            return null;
        }
        return channels;
    }
}
